package com.sentiment.database.bean;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.apache.shiro.crypto.hash.Md5Hash;
import org.bson.Document;
import org.bson.types.ObjectId;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.sentiment.bean.OperationInfo;
import com.sentiment.database.dbUtil.DbUtil;
import com.sentiment.shiro.MyRealm;


public class User{
	@Override
	public String toString() {
		return "User [_id=" + _id + ", username=" + username + ", usercode=" + usercode + ", password=" + password
				+ ", salt=" + salt + ", locked=" + locked
				+ "]";
	}

	public static final String dbName = "UserDB";
	public static final String collection = "User";
	
	private ObjectId _id;
	private String username;
	//昵称（显示在页面，可重复）
	private String usercode;
	//密码
	private String password;
	//盐
	private String salt;
	//账号是否锁定
	private boolean locked;

	public User() {	}
	
	public User(String username, String usercode, String password, String salt, boolean locked) {
		super();
		this.username = username;
		this.usercode = usercode;
		this.password = password;
		this.salt = salt;
		this.locked = locked;
	}

	public Document toDocument(){
		return new Document("username",username).append("usercode", usercode)
		.append("password", password).append("salt", salt)
		.append("locked", locked);
	}
	
	public User(Document doc){
		super();
		_id = doc.getObjectId("_id");
		username = doc.getString("username");
		usercode = doc.getString("usercode");
		password = doc.getString("password");
		salt = doc.getString("salt");
		locked = doc.getBoolean("locked");
	}
	
	public User(String user_id) {
		super();
		this._id = new ObjectId(user_id);
	}

	public String get_id() {
		return _id.toString();
	}

	public void set_id(String _id) {
		this._id = new ObjectId(_id);
	}

	public String getUsername() {
		return username;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	public String getUsercode() {
		return usercode;
	}

	public void setUsercode(String usercode) {
		this.usercode = usercode;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public String getSalt() {
		return salt;
	}

	public void setSalt(String salt) {
		this.salt = salt;
	}

	public boolean isLocked() {
		return locked;
	}

	public void setLocked(boolean locked) {
		this.locked = locked;
	}
	
	
	/**
	 * 根据用户 _id 获取该用户的角色列表
	 * @param user_id
	 * @return
	 */
	public List<Role> getRolesByUser_id(String user_id){
		
		User_Roles user_roles = new User_Roles();
		user_roles = user_roles.getUser_RolesByUser_id(user_id);
		if(user_roles == null)
			return null;
		List<String> roles_id = user_roles.getRoles_id();
		List<Role> roles = new ArrayList<>();
		Role role = new Role();
		for(int i = 0; i < roles_id.size(); i++){
			
			role = role.getRoleByRoleId(roles_id.get(i));
			
			if(role != null)
				roles.add(role);
		}
		return roles;
	}
	
	/**
	 * 根据 UserCode 获取 User
	 * @param usercode
	 * @return
	 */
	public User getUserByUserCode(String usercode){
		
		DbUtil userdb = new DbUtil();
		userdb.openConnection(dbName, collection);
		
		String[] keys = {"usercode"};
		User user = new User(null,usercode,null,null,false);
		Document t = user.toDocument();
		t = userdb.query(t,keys);
		
		userdb.closeConnection();
		
		if(t == null)
			return null;
		
		return new User(t);
	}
	
	/**
	 * 根据用户 _id 获取 User
	 * @param user_id
	 * @return
	 */
	public User getUserByUser_id(String user_id){
		
		DbUtil userdb = new DbUtil();
		userdb.openConnection(dbName, collection);
		
		String[] keys = {"_id"};
		User user = new User(user_id);
		Document t = user.toDocument_id();
		t = userdb.query(t,keys);
		
		userdb.closeConnection();
		
		if(t == null)
			return null;
		
		return new User(t);
	}
	
	/**
	 * 转换为带 _id 的 Document
	 * @return
	 */
	private Document toDocument_id() {
		return new Document("_id", _id).append("username", username).append("usercode", usercode)
				.append("password", password).append("salt", salt)
				.append("locked", locked);
	}
	
	/**
	 * 测试时用于向数据库中写入数据
	 */
	public void test() {
		DbUtil userdb = new DbUtil();
		userdb.openConnection(dbName, collection);
		
		User user = new User("雷克斯(普通用户)","user","f3694f162729b7d0254c6e40260bf15c","qwerty",false);
		Document t = user.toDocument();
		userdb.insert(t);
		
		user = new User("雷克斯(付费用户)","user_pay","f3694f162729b7d0254c6e40260bf15c","qwerty",false);
		t = user.toDocument();
		userdb.insert(t);
		
		user = new User("雷克斯(管理员)","admin","f3694f162729b7d0254c6e40260bf15c","qwerty",false);
		t = user.toDocument();
		userdb.insert(t);

		userdb.closeConnection();
		
	}
	
	/**
	 * 当前用户添加一个角色 
	 * 更改 User_Roles 和 User_Permissions 表
	 * @param role
	 * @return 操作信息
	 */
	public String addRole(Role role){
		
		String rolename = role.getRolename();
		OperationInfo info = new OperationInfo();
		Role roledb = role.getRoleByRoleName(rolename);
		if(roledb == null){
			
			return OperationInfo.RoleNotFound;
		}
			
		User userdb = this.getUserByUser_id(this.get_id());
		if(userdb == null){
			
			return OperationInfo.UserNotFind;
		}
		
		List<Role> roles = new ArrayList<>();
		roles = userdb.getRolesByUser_id(userdb.get_id());
		if(roles != null){
			if(roles.contains(roledb)){
				
				return OperationInfo.UserhasContainsRole;
			}
		}
		
		if(roles == null)
			roles = new ArrayList<>();
		roles.add(roledb);
		
		//更改 User_Roles 表
		User_Roles user_roles = new User_Roles();
		user_roles = user_roles.getUser_RolesByUser_id(userdb.get_id());
		boolean updateUser_Roles ;
		if(user_roles == null){
			DbUtil db = new DbUtil();
			db.openConnection(User_Roles.dbName, User_Roles.collection);
			user_roles = new User_Roles();
			user_roles.setUser_id(userdb.get_id());
			user_roles.setRoles_id(Arrays.asList(roledb.get_id()));
			updateUser_Roles = db.insert(user_roles.toDocument());
			db.closeConnection();
		}
		else{
			updateUser_Roles = user_roles.updateRolesByRoles(roles);
		}
		
		//更改 User_Permissions 表
		User_Permissions user_pers = new User_Permissions();
		user_pers = user_pers.getUser_PermissionsByUser_id(userdb.get_id());
		boolean updateUser_Pers;
		if(user_pers == null){
			user_pers = new User_Permissions();			
			user_pers.setUser_id(this.get_id());
			List<String> permissions_id = new ArrayList<>();
			Role_Permissions role_pers = new Role_Permissions();
			List<Permission> permissions = role_pers.getPermissionListByRole_id(roledb.get_id());
			for(int i = 0; i < permissions.size(); i++){
				permissions_id.add(permissions.get(i).get_id());
			}
			user_pers.setpermissions_id(permissions_id);
			DbUtil db = new DbUtil();
			db.openConnection(User_Permissions.dbName, User_Permissions.collection);
			updateUser_Pers = db.insert(user_pers.toDocument());
			db.closeConnection();
		}
		else{
			updateUser_Pers = user_pers.updatePermissionByRoles(roles);
		}
		
		if(updateUser_Roles && updateUser_Pers)
			return OperationInfo.OperSuccess;
		else
			return OperationInfo.OperFailure;
	}
	
	/**
	 * 当前用户移除一个角色
	 * 更改 User_Roles 和 User_Permissions 表
	 * @param role
	 * @return 操作信息
	 */
	public String removeRole(Role role){
		
		String rolename = role.getRolename();
		OperationInfo info = new OperationInfo();
		Role roledb = role.getRoleByRoleName(rolename);
		if(roledb == null){
			
			return OperationInfo.RoleNotFound;
		}
			
		User userdb = this.getUserByUser_id(this.get_id());
		if(userdb == null){
			
			return OperationInfo.UserNotFind;
		}
		
		List<Role> roles = userdb.getRolesByUser_id(userdb.get_id());
		
		if(roles == null ||! roles.contains(roledb)){
			
			return OperationInfo.UserNotContainsRole;
		}
		
		roles.remove(roledb);
		
		//更改 User_Roles 表
		User_Roles user_roles = new User_Roles();
		user_roles = user_roles.getUser_RolesByUser_id(userdb.get_id());
		boolean updateUser_Roles = user_roles.updateRolesByRoles(roles);
		
		//更改 User_Permissions 表
		User_Permissions user_pers = new User_Permissions();
		user_pers = user_pers.getUser_PermissionsByUser_id(userdb.get_id());
		boolean updateUser_Pers = user_pers.updatePermissionByRoles(roles);
		
		if(updateUser_Roles && updateUser_Pers)
			return OperationInfo.OperSuccess;
		else
			return OperationInfo.OperFailure;
	}
	
	/**
	 * 锁定当前用户
	 * @return 操作信息
	 */
	public String Locked(){
		
		User userdb = new User();
		userdb = userdb.getUserByUser_id(this.get_id());
		OperationInfo info = new OperationInfo();
		if(userdb == null){
			
			return OperationInfo.UserNotFind;
		}
		if(userdb.locked){
			
			return OperationInfo.UserisLocked;
		}
		
		userdb.locked = true;
		DbUtil db = new DbUtil();
		db.openConnection(dbName, collection);
		String []oKeys = {"_id"};
		String []nKeys = {"locked"};
		boolean update = db.update(this.toDocument_id(), oKeys, userdb.toDocument_id(), nKeys);
		db.closeConnection();
		
		if(update)
			return OperationInfo.OperSuccess;
		else
			return OperationInfo.OperFailure;
	}
	
	/**
	 * 解锁当前用户
	 * @return 操作信息
	 */
	public String UnLocked(){
		
		User userdb = new User();
		userdb = userdb.getUserByUser_id(this.get_id());
		String error = "";
		OperationInfo info = new OperationInfo();
		if(userdb == null){
			
			return OperationInfo.UserNotFind;
		}
		if(! userdb.locked){
			
			return OperationInfo.UserisUnLocked;
		}
		
		userdb.locked = false;
		DbUtil db = new DbUtil();
		db.openConnection(dbName, collection);
		String []oKeys = {"_id"};
		String []nKeys = {"locked"};
		boolean update = db.update(this.toDocument_id(), oKeys, userdb.toDocument_id(), nKeys);
		db.closeConnection();
		
		if(update)
			return OperationInfo.OperSuccess;
		else
			return OperationInfo.OperFailure;
	}
	
	/**
	 * 获取 User 表中数据条数
	 * @return
	 */
	@JsonIgnore
	public long getCount(){
		
		DbUtil db = new DbUtil();
		db.openConnection(dbName, collection);
		long count = db.collectionGetCount();
		db.closeConnection();
		return count;
		
	}
	
	/**
	 * 修改该用户密码
	 * @return 操作信息 
	 */
	public String ChargePassword(String password){
		
		User user = this;	
		Md5Hash md5Hash = new Md5Hash(password, this.getSalt(), 1);
		String password_md5 =  md5Hash.toString();
		user.setPassword(password_md5);
		DbUtil db = new DbUtil();
		db.openConnection(User.dbName, User.collection);
		String []okey = {"_id"};
		String []nkey = {"password"};
		boolean update = db.update(user.toDocument_id(), okey, user.toDocument_id(), nkey);
		db.closeConnection();
		if(update){
			MyRealm realm = new MyRealm();
			realm.clearCached();
			return OperationInfo.OperSuccess;
		}else
			return OperationInfo.OperFailure;
		
	}
	

	public static void main(String[] args) {
		User user = new User();
//		List<String> role = user.getRolesByUser_id("561fb2990768660cf0b2ffb5");
//		System.out.println(role.get(0).toString());
		
		user = user.getUserByUser_id("5629f9d753f2260edc2a7312");
		System.out.println(user.getUsername());
		
//		Role role = new Role();
//		role = role.getRoleByRoleId("5625fd0b49e1b208102ad40f");
//		System.out.println(role.getRole_detail());
//		
//		System.out.println(user.removeRole(role));
		
		
		System.out.println(user.Locked());
		
	}

}
